// Copyright (C) 2025, ZWSOFT Co., LTD.(Guangzhou)
// Licensed under the MIT License. See LICENSE in the project root for license information.

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TestClient.Domain;

namespace TestClient.ViewModel;

public partial class GeodesicTestViewModel : PageViewModelBase
{
    [ObservableProperty]
    private string surfaceId = "";
    [ObservableProperty]
    private string curveId = "";
    [ObservableProperty]
    private string startPointId = "";
    [ObservableProperty]
    private string endPointId = "";
    [ObservableProperty]
    private double inquiredDistance;
    [ObservableProperty]
    private double inputDistance;
    [ObservableProperty]
    private string inquiredCoord = "";
    [ObservableProperty]
    private string newCurveId = "";
    [ObservableProperty]
    private string resultId = "";

    [ObservableProperty]
    private string curveName = "ply001Line1";
    [ObservableProperty]
    private string geomsetName = "ExceedWidthLines";

    public IAsyncRelayCommand SelectSurfaceCommand { get; }
    public IAsyncRelayCommand SelectCurveCommand { get; }
    public IAsyncRelayCommand SelectStartPointCommand { get; }
    public IAsyncRelayCommand SelectEndPointCommand { get; }
    public IAsyncRelayCommand CreateCurveCommand { get; }
    public IAsyncRelayCommand InquireDistanceCommand { get; }
    public IAsyncRelayCommand InquireCoordCommand { get; }
    public IAsyncRelayCommand CreateLimitedCurveCommand { get; }

    public GeodesicTestViewModel(VFAdapterWrapper wrapper, ISnackNotifyService notifyService) : base(wrapper, notifyService)
    {
        SelectSurfaceCommand = CreateAsyncRpcCommand(SelectSurface);
        SelectCurveCommand = CreateAsyncRpcCommand(SelectCurve);
        SelectStartPointCommand = CreateAsyncRpcCommand(SelectStartPoint);
        SelectEndPointCommand = CreateAsyncRpcCommand(SelectEndPoint);
        CreateCurveCommand = CreateAsyncRpcCommand(CreateCurve);
        InquireDistanceCommand = CreateAsyncRpcCommand(InquireDistance);
        InquireCoordCommand = CreateAsyncRpcCommand(InquireCoord);
        CreateLimitedCurveCommand = CreateAsyncRpcCommand(CreateLimitedCurve);
    }

    private async Task SelectSurface()
    {
        EnsureConnected();
        SurfaceId = await ViewModelHelpers.SelectEnt(Wrapper, "Surface");
    }
    private async Task SelectCurve()
    {
        EnsureConnected();
        CurveId = await ViewModelHelpers.SelectEnt(Wrapper, "Curve");
    }
    private async Task SelectStartPoint()
    {
        EnsureConnected();
        StartPointId = await ViewModelHelpers.SelectEnt(Wrapper, "Point");
    }
    private async Task SelectEndPoint()
    {
        EnsureConnected();
        EndPointId = await ViewModelHelpers.SelectEnt(Wrapper, "Point");
    }
    private async Task CreateCurve()
    {
        EnsureConnected();
        var ids = await Task.Run(() =>
                {
                    var startPointCoord = Wrapper.GetPointCoord(StartPointId);
                    var endPointCoord = Wrapper.GetPointCoord(EndPointId);
                    return Wrapper.CreateCurveOnSurfaceByTwoPoints3(SurfaceId, [startPointCoord], [endPointCoord]);
                });
        ResultId = string.Join(", ", ids);
    }
    private async Task InquireDistance()
    {
        EnsureConnected();
        InquiredDistance = await Task.Run(() =>
        {
            var startPointCoord = Wrapper.GetPointCoord(StartPointId);
            var endPointCoord = Wrapper.GetPointCoord(EndPointId);
            var dirx = endPointCoord.x - startPointCoord.x;
            var diry = endPointCoord.y - startPointCoord.y;
            var dirz = endPointCoord.z - startPointCoord.z;
            return Wrapper.GeodesicLengthOfPointToCurve(SurfaceId, CurveId, StartPointId, new Vector3d { x = dirx, y = diry, z = dirz });
        });
    }
    private async Task InquireCoord()
    {
        EnsureConnected();
        var coord = await Task.Run(() =>
        {
            var startPointCoord = Wrapper.GetPointCoord(StartPointId);
            var endPointCoord = Wrapper.GetPointCoord(EndPointId);
            var dirx = endPointCoord.x - startPointCoord.x;
            var diry = endPointCoord.y - startPointCoord.y;
            var dirz = endPointCoord.z - startPointCoord.z;
            return Wrapper.GetPointByGeodesicDis(SurfaceId, startPointCoord, new Vector3d() { x = dirx, y = diry, z = dirz }, InputDistance);
        });
        InquiredCoord = coord.ToString();
    }
    private async Task CreateLimitedCurve()
    {
        EnsureConnected();
        NewCurveId = await Task.Run(() =>
        {
            var startPointCoord = Wrapper.GetPointCoord(StartPointId);
            var endPointCoord = Wrapper.GetPointCoord(EndPointId);
            var dirx = endPointCoord.x - startPointCoord.x;
            var diry = endPointCoord.y - startPointCoord.y;
            var dirz = endPointCoord.z - startPointCoord.z;
            var dir = new Vector3d() { x = dirx, y = diry, z = dirz };
            return Wrapper.CreatGeodesicCurvebyPoint(CurveId, SurfaceId, startPointCoord, dir, CurveName, GeomsetName);
        });
    }

}
